﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using System.Threading;

namespace Mp3Tagger
{
	public partial class FmMain : Form
	{
		AudioFilesTools audioFiles = new AudioFilesTools();
		delegate void UpdateRichTextBox(string text);

	    private UpdateRichTextBox _textBoxUpdateDelegate;
        delegate void ChangeButton();
		delegate void SetDatasourceListBox();
        private StatusStripTextBox _sstDelegate;
		delegate void StatusStripTextBox(string text);
        private LastfmWorker _lastfmWorker = new LastfmWorker();


		List<AudioFile> _scanedFiles = new List<AudioFile>();
		Dictionary<string, string> _albumImages = new Dictionary<string, string>();
	    private int _imgPathCounter;
		static object locker = new object();

		public FmMain()
		{
		    _textBoxUpdateDelegate = OnTextBoxUpdate;
		    _sstDelegate = OnStripTextBoxTextChange;
		    InitializeComponent();
		}


	    private void btnGetImageUrl_Click(object sender, EventArgs e)
		{
            var workerThread = new Thread(GetImages);
            workerThread.Start();
	       
		}

		private void GetImages()
		{
            AddTextToLog( string.Format("{1} Get images for {0} albums", _albumImages.Count, DateTime.Now.ToLongTimeString()));
            AddTextToLog( Environment.NewLine);
            _imgPathCounter = 0;
            var tmpalbumImages = _albumImages.Keys.ToDictionary(albumImage => albumImage, albumImage => _albumImages[albumImage]);

            Cursor.Current = Cursors.WaitCursor;

			foreach (var albumImage in tmpalbumImages.Keys)
			{
                ThreadPool.QueueUserWorkItem(GetImage, albumImage);
			}

            lock (locker)
                while (_imgPathCounter + 1 < tmpalbumImages.Count)
                    Monitor.Wait(locker);

            Cursor.Current = Cursors.Default;
		    ChangeButton d = delegate { _btnSaveMP3.Enabled = true; };
            _btnSaveMP3.BeginInvoke(d);
            SetStatusStripText( "Done");
            AddTextToLog(string.Format("{1} {0} images recieved", _imgPathCounter+1, DateTime.Now.ToLongTimeString()));
            AddTextToLog( Environment.NewLine);
		}
        private void GetImage(object instance)
        {
            var albumImage = (string) instance;
            var artist = albumImage.Split(new[] { '_' })[0];
            var album = albumImage.Split(new[] { '_' })[1];
            var albumArtUri = _lastfmWorker.GetAlbumArtUri(artist, album);
 
            AddTextToLog(string.Format("{1} ({0})", albumImage, albumArtUri));
            AddTextToLog(Environment.NewLine);
            var imgPath = audioFiles.GetImageFromWeb(albumArtUri);

            lock (locker)
            {
                _imgPathCounter++;
                if (!string.IsNullOrEmpty(imgPath))
                  _albumImages[albumImage] = imgPath;
            }
            SetStatusStripText(string.Format("{0} of {1} files downloaded", _imgPathCounter, _albumImages.Count));
            lock (locker)
            {
                Monitor.Pulse(locker);
            }
        }

	    private void SetStatusStripText(string text)
	    {
	        statusStrip1.BeginInvoke(_sstDelegate, text);
	    }

	    private void AddTextToLog(string text)
	    {
	        richTextBox1.BeginInvoke(_textBoxUpdateDelegate, text);
	    }

	    private void btnSelectFolder_Click(object sender, EventArgs e)
		{
			if (folderBrowserDialog1.ShowDialog() != DialogResult.OK) return;

			lbFolder.Text = folderBrowserDialog1.SelectedPath;
			var files = System.IO.Directory.GetFiles(folderBrowserDialog1.SelectedPath, "*.mp3",System.IO.SearchOption.AllDirectories);
            _scanedFiles = new List<AudioFile>();
            _albumImages = new Dictionary<string, string>();
			var workerThread = new Thread(ScanFiles);
			workerThread.Start(files);
            btnGetImages.Enabled = true;
		}

		private void ScanFiles(object fileNamesobj)
		{
			var fileNames = (string[])fileNamesobj;
            AddTextToLog( string.Format("{1} Start {0} ScanFiles", fileNames.Length, DateTime.Now.ToLongTimeString()));
            AddTextToLog( Environment.NewLine);
			var counter = 0;
			var totalFiles = fileNames.Length;
			foreach (var filePath in fileNames)
			{
                SetStatusStripText( string.Format("{0} of {1} files scaned", counter + 1, totalFiles));
				var tag = audioFiles.ReadMp3Id3(filePath);
				if (tag == null || tag.Performers.Length < 1 || string.IsNullOrEmpty(tag.Album)) continue;
				lock (locker)
				{
					var newFile = new AudioFile(filePath, tag.Performers[0], tag.Album);
					_scanedFiles.Add(newFile);
					if (!_albumImages.ContainsKey(newFile.Album_Artist))
					{
						_albumImages.Add(newFile.Album_Artist, "");
					}
				}
				counter++;
			}
            SetStatusStripText( "Done");
            AddTextToLog( string.Format("{1} {0} files scaned", counter, DateTime.Now.ToLongTimeString()));
            AddTextToLog( Environment.NewLine);
			SetDatasourceListBox setDatasourceListBox = delegate
															{
																lboxAlbums.DataSource = new BindingSource(_albumImages, null);
																lboxAlbums.DisplayMember = "Key";
																lboxAlbums.ValueMember = "Value";
															};
			lboxAlbums.BeginInvoke(setDatasourceListBox);
		}

		private void _btnSaveMP3_Click(object sender, EventArgs e)
		{
			var workerThread = new Thread(SaveAllFiles);
			workerThread.Start();
		}
        
		private void SaveAllFiles()
		{

			AddTextToLog( string.Format("{1} saving {0} files", _scanedFiles.Count, DateTime.Now.ToLongTimeString()));
			AddTextToLog( Environment.NewLine);
			var counter = 0;
			foreach (var mp3Info in _scanedFiles)
			{
				if(string.IsNullOrEmpty(_albumImages[mp3Info.Album_Artist])) continue;
				audioFiles.SaveImageToFile(mp3Info.FilePath, _albumImages[mp3Info.Album_Artist]);
                SetStatusStripText( string.Format("{0} of {1} files saved", counter + 1, _scanedFiles.Count));
				counter++;
			}
            SetStatusStripText( "Done");
			AddTextToLog( string.Format("{1} {0} files saved", counter, DateTime.Now.ToLongTimeString()));
			AddTextToLog( Environment.NewLine);
		}

	    private void OnTextBoxUpdate(string text)
	    {
	        richTextBox1.AppendText(text);
	    }

	    private void OnStripTextBoxTextChange(string text)
	    {
	        statusStrip1.Items["_SBlable"].Text = text;
	    }

        private void lboxAlbums_SelectedIndexChanged(object sender, EventArgs e)
        {
            
            var selValue =_albumImages[((KeyValuePair<string, string>) lboxAlbums.SelectedItem).Key];
            if (string.IsNullOrEmpty(selValue))
            {
                pictureBox1.Image = null;
                return;
            }
            var immagine = Image.FromFile(selValue);
            pictureBox1.Image = immagine;
        }
	}
}
